package com.example.concurrentprogramming8016.thread.addr;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * @author liyanhao
 * @Date 2023-01-03 22:13
 */
public class LongAdderTest {
    public static void main(String[] args) {
        testAtomicLongVSLongAdder(100, 10000);
        System.out.println("+++++++++++");
        testAtomicLongVSLongAdder(10000, 10000);
        System.out.println("+++++++++++");
        testAtomicLongVSLongAdder(1000, 10000);
        System.out.println("+++++++++++");

    }

    static void testAtomicLongVSLongAdder(final int threadCount, final int times) {
        try {
            long start = System.currentTimeMillis();
            testAtomicLong(threadCount, times);
            long end = System.currentTimeMillis() - start;
            System.out.println("条件>>>>>线程数:" + threadCount + ",单线程操作计数" + times);
            System.out.println("结果>>>>>>AtomicLong方式增加计数" + (threadCount * times) + "次,共耗时：" + end);

            long start2 = System.currentTimeMillis();
            testLongAdder2(threadCount, times);
            long end2 = System.currentTimeMillis() - start2;
            System.out.println("条件>>>>>线程数:" + threadCount + ",单线程操作计数" + times);
            System.out.println("结果>>>>>>LongAdder方式增加计数" + (threadCount * times) + "次,共耗时：" + end2);



        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    static void testAtomicLong(final int threadCount, final int times) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        AtomicLong atomicLong = new AtomicLong();
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < times; j++) {
                    atomicLong.incrementAndGet();
                }
                countDownLatch.countDown();
            }, "my-thread" + i).start();
        }
        //导致当前线程等待，直到锁存器倒计时为零，除非线程被中断。
        //如果当前计数为零，则此方法立即返回。
        //如果当前计数大于零，则当前线程出于线程调度目的而被禁用并处于休眠状态，直到发生以下两种情况之一：
        //由于调用countDown方法，计数达到零；要么
        //其他某个线程中断了当前线程。
        //如果当前线程：
        //在进入此方法时设置其中断状态；要么
        //等待时被打断
        countDownLatch.await();
    }

    static void testLongAdder(final int threadCount, final int times) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        LongAdder longAdder = new LongAdder();
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < times; j++) {
                    longAdder.add(1);
                }
                countDownLatch.countDown();
            }, "my-thread" + i).start();
        }
        countDownLatch.await();

    }
    static void testLongAdder2(final int threadCount, final int times) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        LongAdder longAdder = new LongAdder();
        for (int i = 0; i < threadCount; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < times; j++) {
                        longAdder.add(1);
                    }
                    countDownLatch.countDown();
                }
            }, "my-thread" + i).start();
        }

        countDownLatch.await();
    }
}
